#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QIntValidator>
#include <QDateTime>
#include <QHostAddress>
#include <QHostInfo>
#include <QThread>
#include <windows.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>
#include <QDir>
#include <QMutex>
#include <QApplication>
#include <iostream>//调试输出

// 全局变量，表示是否正在进行测试
bool working = false;

// 全局文本数组
std::string* globalTextArray;

// 全局整数变量 线程数
int threadCount;

// 全局互斥锁，用于保护threadCount
QMutex threadCountMutex;

// 引入网络测试函数声明
extern std::string test_ping(std::string& log, const std::string& local_ip, const std::string& target_ip, int count);
extern std::string test_telnet(std::string& log, const std::string& local_ip, const std::string& target_ip, int port);
extern std::string test_tracert(std::string& log, const std::string& local_ip, const std::string& target_ip, const std::string& protocol, int timeout, int attempts);

// ========== IPScanWorker 类实现 ==========
IPScanWorker::IPScanWorker(QObject *parent) : QObject(parent)
{
}

void IPScanWorker::scanIPAddresses()
{
    // 获取本机IP地址列表
    QStringList ipList;
    
    // 获取所有网络接口
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
    
    // 遍历所有网络接口
    for (int i = 0; i < interfaces.size(); i++) {
        QNetworkInterface iface = interfaces.at(i);
        
        // 排除回环接口和非活动接口
        if (iface.flags().testFlag(QNetworkInterface::IsLoopBack) ||
            !iface.flags().testFlag(QNetworkInterface::IsRunning)) {
            continue;
        }
        
        // 获取接口的IP地址列表
        QList<QNetworkAddressEntry> addresses = iface.addressEntries();
        
        // 遍历接口的IP地址
        for (int j = 0; j < addresses.size(); j++) {
            QNetworkAddressEntry entry = addresses.at(j);
            QHostAddress ip = entry.ip();
            
            // 只添加IPv4地址
            if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
                ipList.append(ip.toString());
            }
        }
    }
    
    // 添加本地回环地址
    if (!ipList.contains("127.0.0.1")) {
        ipList.append("127.0.0.1");
    }
    
    // 添加本机主机名对应的IP
    QString localHostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(localHostName);
    
    // 遍历主机名解析的IP地址
    for (int i = 0; i < hostInfo.addresses().size(); i++) {
        QHostAddress address = hostInfo.addresses().at(i);
        if (address.protocol() == QAbstractSocket::IPv4Protocol && 
            !ipList.contains(address.toString())) {
            ipList.append(address.toString());
        }
    }
    
    // 发送扫描完成信号
    emit ipScanFinished(ipList);
    
    // 发送完成信号
    emit finished();
}

// ========== ListTestWorker 类实现 ==========
ListTestWorker::ListTestWorker(QObject *parent) : QObject(parent)
{
    ui = MainWindow::getInstance()->getUi();
}

void ListTestWorker::setRowIndex(int index)
{
    m_rowIndex = index;
}

void ListTestWorker::doTest()
{
    try {
        // 获取测试参数
        QString testType = ui->tableWidget->item(m_rowIndex, 1)->text();
        QString targetIp = ui->tableWidget->item(m_rowIndex, 3)->text();
        QString port = ui->tableWidget->item(m_rowIndex, 4)->text();
        QString localIp = ui->ipboBox->currentText();
        
        std::string result;
        std::string& log = globalTextArray[m_rowIndex];  // 直接使用引用
        
        if (testType.toLower() == "ping") {
            result = test_ping(log, localIp.toStdString(), targetIp.toStdString(), 10);
        }
        else if (testType.toLower() == "telnet") {
            int portNum = port.toInt();
            if (portNum <= 0) portNum = 80;
            result = test_telnet(log, localIp.toStdString(), targetIp.toStdString(), portNum);
        }
        else if (testType.toLower() == "tracert") {
            result = test_tracert(log, localIp.toStdString(), targetIp.toStdString(), "ICMP", 6000, 3);
        }
        else {
            result = "[不通过]不支持的测试类型";
        }
        
        // 使用安全的方法更新状态列
        MainWindow::getInstance()->updateTableStatus(m_rowIndex, QString::fromStdString(result));
    }
    catch (...) {
        // 使用安全的方法更新状态列
        MainWindow::getInstance()->updateTableStatus(m_rowIndex, "[不通过]测试异常");
    }
    
    // 使用互斥锁保护threadCount的递减操作
    QMutexLocker locker(&threadCountMutex);
    threadCount--;

    emit testFinished();
}

// ========== LogMonitorWorker 类实现 ==========
LogMonitorWorker::LogMonitorWorker(QObject* parent) : QObject(parent), m_logRef(nullptr)
{
}

void LogMonitorWorker::setLogReference(const std::string& logRef)
{
    QMutexLocker locker(&m_mutex);
    m_logRef = &logRef;
    m_lastContent = "";
}

void LogMonitorWorker::startMonitoring()
{
    // 首先检查是否设置了日志引用
    if (!m_logRef) {
        emit finished();
        return;
    }
    
    // 每100毫秒检查一次日志变化
    while (working) {
        QString newContent;
        
        {
            QMutexLocker locker(&m_mutex);
            // 获取当前日志内容
            std::string currentContent = *m_logRef;
            
            // 如果有新内容
            if (currentContent.length() > m_lastContent.length()) {
                // 获取新增部分
                std::string newPart = currentContent.substr(m_lastContent.length());
                // 删除新增内容中的换行符
                newPart.erase(std::remove(newPart.begin(), newPart.end(), '\n'), newPart.end());
                newContent = QString::fromStdString(newPart);
                
                // 更新上次内容
                m_lastContent = currentContent;
            }
        }
        
        // 发送新内容
        if (!newContent.isEmpty()) {
            emit logUpdated(newContent);
        }
        
        // 延时100毫秒
        QThread::msleep(100);
    }
    
    // 测试结束，发出完成信号
    emit finished();
}

// ========== NetTestWorker 类实现 ==========
NetTestWorker::NetTestWorker(QObject* parent) : QObject(parent)
{
}

void NetTestWorker::setParams(const QString& type, const QString& localIp, const QString& targetIp, const QString& port)
{
    m_type = type;
    m_localIp = localIp;
    m_targetIp = targetIp;
    m_port = port;
}

void NetTestWorker::doTest()
{
    // 添加整体try-catch，避免任何未捕获的异常导致程序崩溃
    try {
        if (m_type.isEmpty() || m_localIp.isEmpty() || m_targetIp.isEmpty()) {
            //emit logUpdated("参数不完整，无法执行测试");
            emit testFinished("[不通过]参数不完整");
            return;
        }
        
        std::string log;
        std::string result;
        
        // 创建日志监控线程
        QThread* logMonitorThread = new QThread();
        LogMonitorWorker* logMonitorWorker = new LogMonitorWorker();
        
        // 设置日志引用
        logMonitorWorker->setLogReference(log);
        
        // 将工作对象移动到线程中
        logMonitorWorker->moveToThread(logMonitorThread);
        
        // 连接信号和槽
        connect(logMonitorThread, &QThread::started, logMonitorWorker, &LogMonitorWorker::startMonitoring);
        connect(logMonitorWorker, &LogMonitorWorker::logUpdated, [this](const QString& newLog) {
            emit logUpdated(newLog);
        });
        connect(logMonitorWorker, &LogMonitorWorker::finished, logMonitorThread, &QThread::quit);
        connect(logMonitorWorker, &LogMonitorWorker::finished, logMonitorWorker, &QObject::deleteLater);
        connect(logMonitorThread, &QThread::finished, logMonitorThread, &QObject::deleteLater);
        
        // 启动日志监控线程
        logMonitorThread->start();
        
        try {         
            if (m_type.toLower() == "ping") {
                // 调试信息
               emit logUpdated(QString("测试类型: %1, 本地IP: %2, 目标IP: %3")
                            .arg(m_type).arg(m_localIp).arg(m_targetIp));
                // 执行Ping测试，固定发送10个请求
                result = test_ping(log, m_localIp.toStdString(), m_targetIp.toStdString(), 20);
            }
            else if (m_type.toLower() == "telnet") {
                // 调试信息
                emit logUpdated(QString("测试类型: %1, 本地IP: %2, 目标IP: %3, 端口: %4")
                            .arg(m_type).arg(m_localIp).arg(m_targetIp).arg(m_port));
                // 执行Telnet测试
                int portNum = m_port.toInt();
                if (portNum <= 0) portNum = 80; // 默认使用80端口
                result = test_telnet(log, m_localIp.toStdString(), m_targetIp.toStdString(), portNum);
            }
            else if (m_type.toLower() == "tracert") {
                // 调试信息
               emit logUpdated(QString("测试类型: %1, 本地IP: %2, 目标IP: %3")
                            .arg(m_type).arg(m_localIp).arg(m_targetIp));
                // 执行Tracert测试，协议可使用ICMP,UDP,TCP
                result = test_tracert(log, m_localIp.toStdString(), m_targetIp.toStdString(), "ICMP", 6000, 3);
            }
            else {
                log = "不支持的测试类型: " + m_type.toStdString();
                result = "[不通过]";
            }
        }
        catch (const std::exception& e) {
            log += "\n发生异常: " + std::string(e.what());
            result = "[不通过]";
        }
        catch (...) {
            log += "\n发生未知异常";
            result = "[不通过]";
        }
        
        // 设置工作状态为false - 在测试结束后设置
        working = false;
        
        // 等待日志监控线程结束
        if (logMonitorThread->isRunning()) {
            logMonitorThread->wait(1000); // 最多等待1秒
        }
        
        // 发送最终结果
        emit testFinished(QString::fromStdString(result));
    }
    catch (...) {
        // 最外层的异常处理，确保线程不会崩溃
        emit logUpdated("线程中发生严重错误，测试终止");
        emit testFinished("[不通过]");
    }
    // 设置工作状态为false - 在测试结束后设置
    working = false;
}

// ========== MainWindow 类实现 ==========

// 静态成员初始化
MainWindow* MainWindow::instance = nullptr;

// 构造函数：初始化主窗口
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    setWindowIcon(QIcon(":/images/net.ico"));
    instance = this;
    ui->setupUi(this);
    
    // 启动时检查管理员权限
    if (!checkPermissions()) {
        QMessageBox::critical(this, "权限错误", 
                              "此应用程序需要管理员权限才能正常运行。\n"
                              "请右键点击应用程序，选择\"以管理员身份运行\"后重新启动。");
    }
    
    // 设置端口输入框只接受数字输入，范围1-65535
    ui->editPort->setValidator(new QIntValidator(1, 65535, this));
    
    // 设置主水平布局的比例：表格区域占3/4，控制面板占1/4
    ui->horizontalLayout->setStretch(0, 3); // 表格区域(左侧)占3份
    ui->horizontalLayout->setStretch(1, 1); // 控制面板(右侧)占1份
    
    // 设置表格区域的垂直布局比例：表格占2/3，日志选项卡占1/3
    ui->tableAreaLayout->setStretch(0, 2); // 表格
    ui->tableAreaLayout->setStretch(1, 1); // 日志选项卡
    
    // 确保日志框样式正确应用
    ui->mainLogEdit->setStyleSheet("background-color: black; color: white;");
    ui->threadLogEdit->setStyleSheet("background-color: black; color: white;");
    
    // 初始化表格数据
    initTable();
    
    // 加载表格数据
    loadTableFromJson();
    
    // 创建右键菜单
    createContextMenu();
    
    // 设置表格上下文菜单策略
    ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    
    // 连接信号到更新表格状态的槽函数
    connect(this, &MainWindow::needUpdateStatus, this, [this](int row, const QString& status) {
        if (row >= 0 && row < ui->tableWidget->rowCount() && 
            ui->tableWidget->item(row, 5) != nullptr) {
            ui->tableWidget->item(row, 5)->setText(status);
        }
    }, Qt::QueuedConnection);
    
    // 连接按钮点击信号到对应的槽函数
    connect(ui->btnAdd, &QPushButton::clicked, this, &MainWindow::onAddButtonClick);
    connect(ui->btnModify, &QPushButton::clicked, this, &MainWindow::onModifyButtonClick);
    connect(ui->btnDelete, &QPushButton::clicked, this, &MainWindow::onDeleteButtonClick);
    connect(ui->btnExecute, &QPushButton::clicked, this, &MainWindow::onExecuteButtonClick);
    connect(ui->btnStop, &QPushButton::clicked, this, &MainWindow::onStopButtonClick);
    
    // 连接测试按钮和停止按钮
    connect(ui->btnTest, &QPushButton::clicked, this, &MainWindow::onTestButtonClick);
    connect(ui->btnStop, &QPushButton::clicked, this, &MainWindow::onStopButtonClick);
    
    // 连接表格选择变更信号到槽函数
    connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, this, &MainWindow::onSelectionChanged);
    
    // 连接表格右键菜单信号
    connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, &MainWindow::showTableContextMenu);
    
    // 初始状态下禁用修改和删除按钮，直到选择了一行
    ui->btnModify->setEnabled(false);
    ui->btnDelete->setEnabled(false);
    
    // 确保停止按钮初始状态为禁用
    ui->btnStop->setEnabled(false);
    
    // 初始化IP扫描线程
    initIPScanThread();
    
    // 初始信息记录到日志
    appendMainLog(tr("应用程序启动，时间: %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    appendMainLog(tr("线程初始化完成"));
}

// 析构函数：清理资源
MainWindow::~MainWindow()
{
    // 如果线程正在运行，等待线程结束
    if (ipScanThread && ipScanThread->isRunning()) {
        ipScanThread->quit();
        ipScanThread->wait();
    }
    
    // 如果有网络测试线程正在运行，也需要停止
    if (working && netTestThread && netTestThread->isRunning()) {
        netTestThread->quit();
        netTestThread->wait();
        working = false;
    }
    
    // 释放线程和工作对象资源
    if (ipScanWorker) {
        delete ipScanWorker;
    }
    
    if (ipScanThread) {
        delete ipScanThread;
    }
    
    if (netTestWorker) {
        delete netTestWorker;
    }
    
    if (netTestThread) {
        delete netTestThread;
    }
    
    // 释放右键菜单资源
    delete tableContextMenu;
    
    delete ui;
}

// 初始化IP扫描线程
void MainWindow::initIPScanThread()
{
    // 记录线程开始
    appendMainLog(tr("开始初始化IP扫描线程"));
    
    // 创建线程和工作对象
    ipScanThread = new QThread(this);
    ipScanWorker = new IPScanWorker();
    
    // 将工作对象移动到线程中
    ipScanWorker->moveToThread(ipScanThread);
    
    // 连接信号和槽
    connect(ipScanThread, &QThread::started, ipScanWorker, &IPScanWorker::scanIPAddresses);
    connect(ipScanWorker, &IPScanWorker::finished, ipScanThread, &QThread::quit);
    connect(ipScanWorker, &IPScanWorker::finished, ipScanWorker, &QObject::deleteLater);
    connect(ipScanThread, &QThread::finished, ipScanThread, &QObject::deleteLater);
    connect(ipScanWorker, &IPScanWorker::ipScanFinished, this, &MainWindow::onIPScanFinished);
    
    // 启动线程
    ipScanThread->start();
    
    appendMainLog(tr("IP扫描线程已启动"));
}

// 处理IP扫描完成
void MainWindow::onIPScanFinished(const QStringList &ipList)
{
    // 将IP地址添加到ipboBox下拉框
    ui->ipboBox->clear();
    ui->ipboBox->addItems(ipList);
    
    appendMainLog(tr("IP地址扫描完成，共找到 %1 个IP地址").arg(ipList.size()));
    appendMainLog(tr("地址：%1").arg(ipList.join(", ")));
}

// 创建表格右键菜单
void MainWindow::createContextMenu()
{
    // 创建表格右键菜单
    tableContextMenu = new QMenu(this);
    
    // 创建菜单项
    selectAllAction = new QAction(tr("全选"), this);
    invertSelectionAction = new QAction(tr("反选"), this);
    deselectAllAction = new QAction(tr("全不选"), this);
    moveUpAction = new QAction(tr("上移"), this);
    moveDownAction = new QAction(tr("下移"), this);
    
    // 添加菜单项到右键菜单
    tableContextMenu->addAction(selectAllAction);
    tableContextMenu->addAction(invertSelectionAction);
    tableContextMenu->addAction(deselectAllAction);
    tableContextMenu->addSeparator();
    tableContextMenu->addAction(moveUpAction);
    tableContextMenu->addAction(moveDownAction);
    
    // 添加分隔线
    tableContextMenu->addSeparator();
    
    // 添加日志菜单项
    QAction* viewLogAction = new QAction(tr("日志"), this);
    tableContextMenu->addAction(viewLogAction);
    
    // 连接菜单项的触发信号到相应的槽函数
    connect(selectAllAction, &QAction::triggered, this, &MainWindow::onSelectAll);
    connect(invertSelectionAction, &QAction::triggered, this, &MainWindow::onInvertSelection);
    connect(deselectAllAction, &QAction::triggered, this, &MainWindow::onDeselectAll);
    connect(moveUpAction, &QAction::triggered, this, &MainWindow::onMoveUp);
    connect(moveDownAction, &QAction::triggered, this, &MainWindow::onMoveDown);
    
    // 连接日志菜单项的触发信号
    connect(viewLogAction, &QAction::triggered, this, &MainWindow::onViewLog);
}

// 显示表格上下文菜单
void MainWindow::showTableContextMenu(const QPoint& pos)
{
    // 将坐标转换为全局坐标
    QPoint globalPos = ui->tableWidget->mapToGlobal(pos);
    
    // 获取当前选中行
    int currentRow = ui->tableWidget->currentRow();
    
    // 根据当前选中状态启用/禁用某些菜单项
    moveUpAction->setEnabled(currentRow > 0);
    moveDownAction->setEnabled(currentRow >= 0 && currentRow < ui->tableWidget->rowCount() - 1);
    
    // 显示菜单
    tableContextMenu->exec(globalPos);
}

// 全选
void MainWindow::onSelectAll()
{
    for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
        QTableWidgetItem* item = ui->tableWidget->item(i, 0);
        if (item) {
            item->setCheckState(Qt::Checked);
        }
    }
    //appendMainLog(tr("全选操作完成"));
}

// 反选
void MainWindow::onInvertSelection()
{
    for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
        QTableWidgetItem* item = ui->tableWidget->item(i, 0);
        if (item) {
            item->setCheckState(item->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked);
        }
    }
    //appendMainLog(tr("反选操作完成"));
}

// 全不选
void MainWindow::onDeselectAll()
{
    for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
        QTableWidgetItem* item = ui->tableWidget->item(i, 0);
        if (item) {
            item->setCheckState(Qt::Unchecked);
        }
    }
    //appendMainLog(tr("全不选操作完成"));
}

// 上移
void MainWindow::onMoveUp()
{
    // 获取当前选中行
    int currentRow = ui->tableWidget->currentRow();
    if (currentRow > 0) {
        // 保存当前行和上一行的数据
        QList<QTableWidgetItem*> currentRowItems;
        QList<QTableWidgetItem*> aboveRowItems;
        
        for (int col = 0; col < ui->tableWidget->columnCount(); col++) {
            QTableWidgetItem* currentItem = ui->tableWidget->takeItem(currentRow, col);
            QTableWidgetItem* aboveItem = ui->tableWidget->takeItem(currentRow - 1, col);
            
            currentRowItems.append(currentItem);
            aboveRowItems.append(aboveItem);
        }
        
        // 交换两行的数据
        for (int col = 0; col < ui->tableWidget->columnCount(); col++) {
            ui->tableWidget->setItem(currentRow - 1, col, currentRowItems.at(col));
            ui->tableWidget->setItem(currentRow, col, aboveRowItems.at(col));
        }
        
        // 选中移动后的行
        ui->tableWidget->setCurrentCell(currentRow - 1, ui->tableWidget->currentColumn());
        
        appendMainLog(tr("将第 %1 行上移至第 %2 行").arg(currentRow + 1).arg(currentRow));
        
        // 保存表格数据到JSON文件
        saveTableToJson();
    }
}

// 下移
void MainWindow::onMoveDown()
{
    // 获取当前选中行
    int currentRow = ui->tableWidget->currentRow();
    if (currentRow < ui->tableWidget->rowCount() - 1) {
        // 保存当前行和下一行的数据
        QList<QTableWidgetItem*> currentRowItems;
        QList<QTableWidgetItem*> belowRowItems;
        
        for (int col = 0; col < ui->tableWidget->columnCount(); col++) {
            QTableWidgetItem* currentItem = ui->tableWidget->takeItem(currentRow, col);
            QTableWidgetItem* belowItem = ui->tableWidget->takeItem(currentRow + 1, col);
            
            currentRowItems.append(currentItem);
            belowRowItems.append(belowItem);
        }
        
        // 交换两行的数据
        for (int col = 0; col < ui->tableWidget->columnCount(); col++) {
            ui->tableWidget->setItem(currentRow + 1, col, currentRowItems.at(col));
            ui->tableWidget->setItem(currentRow, col, belowRowItems.at(col));
        }
        
        // 选中移动后的行
        ui->tableWidget->setCurrentCell(currentRow + 1, ui->tableWidget->currentColumn());
        
        appendMainLog(tr("将第 %1 行下移至第 %2 行").arg(currentRow + 1).arg(currentRow + 2));
        
        // 保存表格数据到JSON文件
        saveTableToJson();
    }
}

// 查看选中行的测试日志
void MainWindow::onViewLog()
{
    // 获取当前选中的行
    int selectedRow = -1;
    QList<QTableWidgetItem*> selectedItems = ui->tableWidget->selectedItems();
    if (!selectedItems.isEmpty()) {
        selectedRow = selectedItems.first()->row();
    }
    
    // 如果没有选中行，直接返回
    if (selectedRow < 0 || selectedRow >= ui->tableWidget->rowCount()) {
        return;
    }
    
    // 获取状态文本
    QString status;
    if (ui->tableWidget->item(selectedRow, 5) != nullptr) {
        status = ui->tableWidget->item(selectedRow, 5)->text();
    } else {
        return;
    }
    
    // 检查状态文本是否包含 "["，并安全地访问globalTextArray
    if (status.contains("[") && globalTextArray != nullptr) {
        // 获取表格的总行数，用于检查数组访问的安全性
        int rowCount = ui->tableWidget->rowCount();
        
        // 确保selectedRow在有效范围内
        if (selectedRow >= 0 && selectedRow < rowCount) {
            // 清空线程日志框
            ui->threadLogEdit->clear();
            
            // 安全地获取并设置线程日志框文本
            std::string logText = globalTextArray[selectedRow];
            
            // 检查日志文本是否有内容
            if (!logText.empty()) {
                ui->threadLogEdit->setPlainText(QString::fromStdString(logText));
            } else {
                // 日志为空的处理
                ui->threadLogEdit->setPlainText("该测试没有详细日志记录");
            }
            
            // 切换到线程日志选项卡
            ui->logTabWidget->setCurrentIndex(1); // 切换到线程日志选项卡
        }
    }
}

// 执行按钮点击处理函数
void MainWindow::onExecuteButtonClick()
{
    appendMainLog(tr("执行操作开始，时间：%1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    appendMainLog(tr("开始执行列表内网络测试"));
    
    working = true;

    // 清除并重新定义全局数组
    delete[] globalTextArray;
    globalTextArray = new std::string[ui->tableWidget->rowCount()];
    
    std::cout << "onExecuteButtonClick_start\n";
    std::cout.flush();
    // 创建执行列表线程
    QThread* executeThread = new QThread();
    QObject* worker = new QObject();
    worker->moveToThread(executeThread);
    
    // 连接线程开始信号到工作函数
    connect(executeThread, &QThread::started, worker, [this]() {
        // 遍历表格所有行
        for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
            // 等待线程数小于5
            while (true) {
                QMutexLocker locker(&threadCountMutex);
                if (threadCount < 5) break;
                locker.unlock();
                QThread::msleep(100);
            }
            
            // 检查该行是否被勾选
            if (ui->tableWidget->item(i, 0)->checkState() == Qt::Checked) {
                std::cout << "onExecuteButtonClick_worker" << i << "\n";
                std::cout.flush();
                
                // 使用安全方法更新状态为执行中
                updateTableStatus(i, "执行中...");
                
                std::cout << "onExecuteButtonClick_worker_table" << i << "\n";
                std::cout.flush();
                
                // 创建并启动ListTestWorker线程
                QThread* thread = new QThread();
                ListTestWorker* worker = new ListTestWorker();
                worker->setRowIndex(i);
                worker->moveToThread(thread);
                
                connect(thread, &QThread::started, worker, &ListTestWorker::doTest);
                connect(worker, &ListTestWorker::testFinished, thread, &QThread::quit);
                connect(worker, &ListTestWorker::testFinished, worker, &QObject::deleteLater);
                connect(thread, &QThread::finished, thread, &QObject::deleteLater);
                
                // 增加线程计数
                QMutexLocker locker(&threadCountMutex);
                threadCount++;
                
                // 启动线程
                thread->start();
            }
            if (working == false) {
                break;
            }
        }
        while (true) {
            if (threadCount == 0) {
                appendMainLog(tr("列表内网络测试完成"));
                break;
            }
            QThread::msleep(100);
        }
        working = false;
        // 恢复按钮状态
        ui->btnTest->setEnabled(true);
        ui->btnExecute->setEnabled(true);
        ui->btnStop->setEnabled(false);
    });
    
    // 连接线程结束信号到清理函数
    connect(executeThread, &QThread::finished, worker, &QObject::deleteLater);
    connect(executeThread, &QThread::finished, executeThread, &QObject::deleteLater);
    
    // 启动执行列表线程
    executeThread->start();

    // 更新按钮状态
    ui->btnTest->setEnabled(false);
    ui->btnExecute->setEnabled(false);
    ui->btnStop->setEnabled(true);
}

// 停止按钮点击处理函数
void MainWindow::onStopButtonClick()
{
    // 检查是否有测试在运行
    if (!working) {
        appendMainLog("没有正在运行的测试任务");
        return;
    }
    
    // 标记工作状态为停止
    working = false;
    appendMainLog("正在安全停止测试...");
    appendMainLog("用户请求停止测试");
    
    // 如果有网络测试线程正在运行，停止它
    if (netTestThread && netTestThread->isRunning()) {
        // 请求中断，然后让线程自行结束
        netTestThread->requestInterruption();
        netTestThread->quit();
        
        // 给线程一些时间来自行结束
        if (!netTestThread->wait(2000)) { // 等待最多2秒
            appendMainLog("警告：线程无法在超时时间内结束，强制终止");
            netTestThread->terminate(); // 只有在必要时才强制终止
            netTestThread->wait();      // 等待终止完成
        }
    }
    
    // 清理资源
    if (netTestWorker) {
        netTestWorker->deleteLater();
        netTestWorker = nullptr;
    }
    
    if (netTestThread) {
        netTestThread->deleteLater();
        netTestThread = nullptr;
    }
    
    // 恢复按钮状态
    ui->btnTest->setEnabled(true);
    ui->btnExecute->setEnabled(true);
    ui->btnStop->setEnabled(false);
    
    appendMainLog("测试已停止");
}

// 检查当前程序是否有管理员权限
bool MainWindow::checkPermissions()
{
    BOOL isAdmin = FALSE;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
    PSID AdministratorsGroup;
    
    // 尝试获取管理员组SID
    if(AllocateAndInitializeSid(
        &NtAuthority,
        2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0,
        &AdministratorsGroup))
    {
        // 检查当前token是否属于管理员组
        if (!CheckTokenMembership(NULL, AdministratorsGroup, &isAdmin)) {
            isAdmin = FALSE;
        }
        
        FreeSid(AdministratorsGroup);
    }
    
    return isAdmin;
}

// 测试按钮点击处理函数
void MainWindow::onTestButtonClick()
{
    // 如果已经有测试在运行，则不启动新的测试
    if (working) {
        QMessageBox::warning(this, "警告", "已有测试正在进行，请先停止");
        return;
    }
    
    // 获取workboBox的所有项目并输出到日志中，用于调试
    for (int i = 0; i < ui->workboBox->count(); ++i) {
        appendMainLog(tr("workboBox项目 %1: %2").arg(i).arg(ui->workboBox->itemText(i)));
    }
    
    // 获取工作类型和目标IP
    QString testType = ui->workboBox->currentText(); // 使用workboBox选中的测试类型
    QString targetIp = ui->editIP->text(); // 使用editIP的值
    QString port = ui->editPort->text(); // 使用editPort的值
    QString localIp = ui->ipboBox->currentText();
    
    // 输出选择的值，用于调试
    appendMainLog(tr("已选择: 类型=%1, 目标IP=%2, 端口=%3, 本地IP=%4")
                   .arg(testType).arg(targetIp).arg(port).arg(localIp));
    
    // 验证参数是否完整
    if (testType.isEmpty()) {
        QMessageBox::warning(this, "提示", "请先选择一个测试类型");
        return;
    }
    
    if (targetIp.isEmpty()) {
        QMessageBox::warning(this, "提示", "请先输入目标IP地址");
        return;
    }
    
    // 如果是telnet测试但没有输入端口，提供默认端口
    if (testType.toLower() == "telnet" && port.isEmpty()) {
        port = "80"; // 默认使用80端口
    }
    
    // 设置工作状态为正在工作
    working = true;
    
    // 更新按钮状态
    ui->btnTest->setEnabled(false);
    ui->btnExecute->setEnabled(false);
    ui->btnStop->setEnabled(true);

    // 清空线程日志
    ui->threadLogEdit->clear(); 
    
    // 手动切换到线程日志标签页
    ui->logTabWidget->setCurrentIndex(1);
    
    // 启动测试线程
    initNetTestThread(testType, localIp, targetIp, port);
}

// 初始化网络测试线程
void MainWindow::initNetTestThread(const QString& testType, const QString& localIp, 
                                   const QString& targetIp, const QString& port)
{
    // 记录线程开始
    appendThreadLog(tr("正在初始化网络测试线程，类型: %1").arg(testType));
    
    // 首先确保没有旧的测试线程在运行
    if (netTestThread) {
        if (netTestThread->isRunning()) {
            netTestThread->quit();
            netTestThread->wait();
        }
        delete netTestThread;
        netTestThread = nullptr;
    }
    
    if (netTestWorker) {
        delete netTestWorker;
        netTestWorker = nullptr;
    }
    
    // 创建线程和工作对象
    netTestThread = new QThread(this);
    netTestWorker = new NetTestWorker();
    
    // 设置测试参数
    netTestWorker->setParams(testType, localIp, targetIp, port);
    
    // 将工作对象移动到线程中
    netTestWorker->moveToThread(netTestThread);
    
    // 连接信号和槽
    connect(netTestThread, &QThread::started, netTestWorker, &NetTestWorker::doTest);
    connect(netTestWorker, &NetTestWorker::testFinished, this, &MainWindow::onTestFinished);
    connect(netTestWorker, &NetTestWorker::logUpdated, this, &MainWindow::onTestLogUpdated);
    connect(netTestWorker, &NetTestWorker::testFinished, netTestThread, &QThread::quit);
    
    // 确保线程结束时自动清理资源
    connect(netTestThread, &QThread::finished, [this]() {
        // 线程结束后清理资源 - 使用deleteLater避免对象仍在使用时被删除
        if (netTestWorker) {
            netTestWorker->deleteLater();
            netTestWorker = nullptr;
        }
        if (netTestThread) {
            netTestThread->deleteLater();
            netTestThread = nullptr;
        }
        // 重置工作状态
        working = false;
        appendThreadLog("测试线程已结束");
    });
    
    // 启动线程
    netTestThread->start();
    
    appendThreadLog("网络测试线程已启动");
}

// 处理网络测试日志更新
void MainWindow::onTestLogUpdated(const QString &log)
{
    // 添加到线程日志中
    appendThreadLog(log);
}

// 处理网络测试完成
void MainWindow::onTestFinished(const QString &result)
{ 
    // 记录测试完成
    appendThreadLog(tr("测试完成，结果: %1").arg(result));
    
    // 重置工作状态
    working = false;
    
    // 恢复按钮状态
    ui->btnTest->setEnabled(true);
    ui->btnExecute->setEnabled(true);
    ui->btnStop->setEnabled(false);
}

// 添加日志到主日志窗口
void MainWindow::appendMainLog(const QString& log)
{
    QString timeStamp = QDateTime::currentDateTime().toString("[hh:mm:ss] ");
    ui->mainLogEdit->append(timeStamp + log);
    // 确保样式应用
    ui->mainLogEdit->setStyleSheet("background-color: black; color: white;");
}

// 添加日志到线程日志窗口
void MainWindow::appendThreadLog(const QString& log)
{
    //QString timeStamp = QDateTime::currentDateTime().toString("[hh:mm:ss] ");
    ui->threadLogEdit->append(log);
    // 确保样式应用
    ui->threadLogEdit->setStyleSheet("background-color: black; color: white;");
}

// 初始化表格：设置列宽并添加测试数据
void MainWindow::initTable()
{
    // 设置表格各列的宽度
    ui->tableWidget->setColumnWidth(0, 40);  // 复选框列
    ui->tableWidget->setColumnWidth(1, 100); // 任务列
    ui->tableWidget->setColumnWidth(2, 120); // 备注列
    ui->tableWidget->setColumnWidth(3, 120); // IP列
    ui->tableWidget->setColumnWidth(4, 80);  // 端口列
    ui->tableWidget->setColumnWidth(5, 300); // 状态列
}

// 保存表格数据到JSON文件
void MainWindow::saveTableToJson()
{
    // 创建JSON数组存储表格数据
    QJsonArray tableData;
    
    // 遍历表格所有行
    for (int row = 0; row < ui->tableWidget->rowCount(); row++) {
        QJsonObject rowData;
        
        // 保存复选框状态
        /* bool isChecked = ui->tableWidget->item(row, 0)->checkState() == Qt::Checked;
        rowData["checked"] = isChecked; */
        
        // 保存其他列数据
        rowData["work"] = ui->tableWidget->item(row, 1)->text();
        rowData["remark"] = ui->tableWidget->item(row, 2)->text();
        rowData["ip"] = ui->tableWidget->item(row, 3)->text();
        rowData["port"] = ui->tableWidget->item(row, 4)->text();
        /* rowData["status"] = ui->tableWidget->item(row, 5)->text(); */
        
        // 添加行数据到数组
        tableData.append(rowData);
    }
    
    // 创建JSON文档
    QJsonDocument document(tableData);
    
    // 将JSON数据保存到文件
    QFile file("tableWidget.json");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write(document.toJson());
        file.close();
        appendMainLog("表格数据已保存到tableWidget.json文件");
    } else {
        appendMainLog("错误：无法保存表格数据到tableWidget.json文件");
    }
}

// 从JSON文件加载表格数据
void MainWindow::loadTableFromJson()
{
    QFile file("tableWidget.json");
    
    // 检查文件是否存在
    if (!file.exists()) {
        appendMainLog("表格数据文件不存在，使用初始空表格");
        return;
    }
    
    // 尝试打开文件
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        appendMainLog("错误：无法打开tableWidget.json文件进行读取");
        return;
    }
    
    // 读取文件内容
    QByteArray jsonData = file.readAll();
    file.close();
    
    // 检查文件是否为空
    if (jsonData.isEmpty()) {
        appendMainLog("表格数据文件为空，使用初始空表格");
        return;
    }
    
    // 解析JSON数据
    QJsonParseError parseError;
    QJsonDocument document = QJsonDocument::fromJson(jsonData, &parseError);
    
    // 检查JSON解析是否成功
    if (parseError.error != QJsonParseError::NoError) {
        appendMainLog("错误：JSON数据格式不正确 - " + parseError.errorString());
        return;
    }
    
    // 检查JSON文档是否包含数组
    if (!document.isArray()) {
        appendMainLog("错误：JSON数据格式不正确，应为数组格式");
        return;
    }
    
    // 清空表格现有数据
    while (ui->tableWidget->rowCount() > 0) {
        ui->tableWidget->removeRow(0);
    }
    
    // 获取JSON数组
    QJsonArray tableData = document.array();
    
    // 逐行添加数据到表格
    for (int i = 0; i < tableData.size(); i++) {
        // 检查当前项是否为对象
        if (!tableData[i].isObject()) {
            appendMainLog(QString("警告：第%1行数据格式不正确，已跳过").arg(i+1));
            continue;
        }
        
        QJsonObject rowData = tableData[i].toObject();
        
        // 检查必要字段是否存在
        if (!rowData.contains("work") || !rowData.contains("remark") || 
            !rowData.contains("ip") || !rowData.contains("port")) {
            appendMainLog(QString("警告：第%1行数据缺少必要字段，已跳过").arg(i+1));
            continue;
        }
        
        // 在表格中添加新行
        int row = ui->tableWidget->rowCount();
        ui->tableWidget->insertRow(row);
        
        // 添加复选框
        QTableWidgetItem* checkItem = new QTableWidgetItem();
        bool isChecked = rowData.value("checked").toBool();
        checkItem->setCheckState(isChecked ? Qt::Checked : Qt::Unchecked);
        ui->tableWidget->setItem(row, 0, checkItem);
        
        // 设置其他列数据
        ui->tableWidget->setItem(row, 1, new QTableWidgetItem(rowData.value("work").toString()));
        ui->tableWidget->setItem(row, 2, new QTableWidgetItem(rowData.value("remark").toString()));
        ui->tableWidget->setItem(row, 3, new QTableWidgetItem(rowData.value("ip").toString()));
        ui->tableWidget->setItem(row, 4, new QTableWidgetItem(rowData.value("port").toString()));
        ui->tableWidget->setItem(row, 5, new QTableWidgetItem("")); // 为状态列添加空项
    }
    
    appendMainLog(QString("成功从tableWidget.json加载了%1行数据").arg(ui->tableWidget->rowCount()));
}

// 清空所有输入框
void MainWindow::clearInputFields()
{
    ui->workboBox->setCurrentIndex(0); // 重置任务下拉框到第一项
    ui->editRemark->clear();
    ui->editIP->clear();
    ui->editPort->clear();
}

// 将选中行的数据更新到输入框中
void MainWindow::updateSelectedRowData()
{
    // 获取当前选中的行
    QList<QTableWidgetItem*> selectedItems = ui->tableWidget->selectedItems();
    if (selectedItems.isEmpty()) {
        clearInputFields();
        return;
    }
    
    int row = selectedItems.first()->row();
    
    // 将选中行的数据填充到输入框中
    // 设置任务下拉框选择项
    QString taskText = ui->tableWidget->item(row, 1)->text();
    int taskIndex = ui->workboBox->findText(taskText);
    if (taskIndex >= 0) {
        ui->workboBox->setCurrentIndex(taskIndex);
    }
    
    ui->editRemark->setText(ui->tableWidget->item(row, 2)->text());
    ui->editIP->setText(ui->tableWidget->item(row, 3)->text());
    ui->editPort->setText(ui->tableWidget->item(row, 4)->text());
}

// 添加按钮点击处理函数
void MainWindow::onAddButtonClick()
{
    // 获取输入框中的数据
    QString work = ui->workboBox->currentText(); // 获取当前选中的任务类型
    QString remark = ui->editRemark->text();
    QString ip = ui->editIP->text();
    QString port = ui->editPort->text();
    
    // 验证输入数据是否完整
    if (remark.isEmpty() || ip.isEmpty()) {
        QMessageBox::warning(this, "提示", "请填写完整信息");
        return;
    }
    
    // 在表格末尾添加新行
    int row = ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(row);
    
    // 添加复选框
    QTableWidgetItem* checkItem = new QTableWidgetItem();
    checkItem->setCheckState(Qt::Unchecked);
    ui->tableWidget->setItem(row, 0, checkItem);
    
    // 设置新行的数据
    ui->tableWidget->setItem(row, 1, new QTableWidgetItem(work));       // 设置任务类型
    ui->tableWidget->setItem(row, 2, new QTableWidgetItem(remark));     // 设置备注
    ui->tableWidget->setItem(row, 3, new QTableWidgetItem(ip));         // 设置IP
    ui->tableWidget->setItem(row, 4, new QTableWidgetItem(port));       // 设置端口
    ui->tableWidget->setItem(row, 5, new QTableWidgetItem(""));         // 为状态列添加空项
    
    // 清空输入框
    clearInputFields();
    
    // 记录日志
    appendMainLog(tr("添加新网络连接：[%1] %2 (%3:%4)").arg(work).arg(remark).arg(ip).arg(port));
    
    // 保存表格数据到JSON文件
    saveTableToJson();
    
    // 显示添加成功提示
    QMessageBox::information(this, "提示", "添加成功");
}

// 修改按钮点击处理函数
void MainWindow::onModifyButtonClick()
{
    // 获取当前选中的行
    QList<QTableWidgetItem*> selectedItems = ui->tableWidget->selectedItems();
    if (selectedItems.isEmpty()) {
        QMessageBox::warning(this, "提示", "请先选择一行");
        return;
    }
    
    int row = selectedItems.first()->row();
    
    // 获取输入框中的数据
    QString work = ui->workboBox->currentText(); // 获取当前选中的任务类型
    QString remark = ui->editRemark->text();
    QString ip = ui->editIP->text();
    QString port = ui->editPort->text();
    
    // 获取原始数据用于日志记录
    QString oldWork = ui->tableWidget->item(row, 1)->text();
    QString oldRemark = ui->tableWidget->item(row, 2)->text();
    QString oldIP = ui->tableWidget->item(row, 3)->text();
    QString oldPort = ui->tableWidget->item(row, 4)->text();
    
    // 验证输入数据是否完整
    if (remark.isEmpty() || ip.isEmpty()) {
        QMessageBox::warning(this, "提示", "请填写完整信息");
        return;
    }
    
    // 更新选中行的数据
    ui->tableWidget->item(row, 1)->setText(work);    // 更新任务类型
    ui->tableWidget->item(row, 2)->setText(remark);  // 更新备注
    ui->tableWidget->item(row, 3)->setText(ip);      // 更新IP
    ui->tableWidget->item(row, 4)->setText(port);    // 更新端口
    
    // 记录日志
    appendMainLog(tr("修改网络连接：[%1] %2 (%3:%4) -> [%5] %6 (%7:%8)")
                  .arg(oldWork).arg(oldRemark).arg(oldIP).arg(oldPort)
                  .arg(work).arg(remark).arg(ip).arg(port));
    
    // 保存表格数据到JSON文件
    saveTableToJson();
    
    // 显示修改成功提示
    QMessageBox::information(this, "提示", "修改成功");
}

// 删除按钮点击处理函数
void MainWindow::onDeleteButtonClick()
{
    // 获取当前选中的行
    QList<QTableWidgetItem*> selectedItems = ui->tableWidget->selectedItems();
    if (selectedItems.isEmpty()) {
        QMessageBox::warning(this, "提示", "请先选择一行");
        return;
    }
    
    int row = selectedItems.first()->row();
    
    // 获取要删除的数据用于日志记录
    QString work = ui->tableWidget->item(row, 1)->text();
    QString remark = ui->tableWidget->item(row, 2)->text();
    QString ip = ui->tableWidget->item(row, 3)->text();
    QString port = ui->tableWidget->item(row, 4)->text();
    
    // 删除选中的行
    ui->tableWidget->removeRow(row);
    
    // 清空输入框
    clearInputFields();
    
    // 禁用修改和删除按钮
    ui->btnModify->setEnabled(false);
    ui->btnDelete->setEnabled(false);
    
    // 记录日志
    appendMainLog(tr("删除网络连接：[%1] %2 (%3:%4)").arg(work).arg(remark).arg(ip).arg(port));
    
    // 保存表格数据到JSON文件
    saveTableToJson();
    
    // 显示删除成功提示
    QMessageBox::information(this, "提示", "删除成功");
}

// 表格选择变更处理函数
void MainWindow::onSelectionChanged()
{
    // 获取当前选中的行
    QList<QTableWidgetItem*> selectedItems = ui->tableWidget->selectedItems();
    bool hasSelection = !selectedItems.isEmpty();
    
    // 根据是否有选中行来启用或禁用修改和删除按钮
    ui->btnModify->setEnabled(hasSelection);
    ui->btnDelete->setEnabled(hasSelection);
    
    // 如果有选中行，更新输入框数据；否则清空输入框
    if (hasSelection) {
        updateSelectedRowData();
    } else {
        clearInputFields();
    }
}

// 更新表格状态的方法实现
void MainWindow::updateTableStatus(int row, const QString& status)
{
    // 在主线程中安全更新UI
    if (QThread::currentThread() == QApplication::instance()->thread()) {
        // 已经在主线程中，直接更新
        if (row >= 0 && row < ui->tableWidget->rowCount() && 
            ui->tableWidget->item(row, 5) != nullptr) {
            ui->tableWidget->item(row, 5)->setText(status);
            // 刷新表格视图
            ui->tableWidget->viewport()->update();
        }
    } else {
        // 在工作线程中，使用信号-槽机制安全地更新UI
        emit needUpdateStatus(row, status);
    }
}

